import frappe
from light_mes.api import (
    generate_tracking_numbers,  
    get_cached_value
)
from frappe.utils import flt


def sync_employees_user_permission(doc, method):
    """
    删除或添加维护的员工对应的用户权限限制记录
    """    

    if doc.has_value_changed("employees"):
        before_save = doc.get_doc_before_save()
        old_employees = {r.employee for r in before_save.employees} if before_save else set()
        new_employees = {r.employee for r in doc.employees}
        employee_user_map = frappe._dict(frappe.get_all("Employee", 
            filters = {
                "name": ("in", old_employees.union(new_employees))
            },
            fields=["name", "user_id"],
            as_list=1
        ))
        for employee in (new_employees - old_employees):
            user = employee_user_map.get(employee)
            if user:
                if not frappe.db.exists("User Permission", {
                    "user": user,
                    "allow": doc.doctype,
                    "for_value": doc.name
                }):
                    frappe.get_doc({
                        "doctype": "User Permission",
                        "user": user,
                        "allow": doc.doctype,
                        "for_value": doc.name
                    }).insert(
                        ignore_permissions=True, 
                        ignore_if_duplicate=True,
                        ignore_links=True
                    )                
        for employee in (old_employees - new_employees):
            user = employee_user_map.get(employee)
            if user:
                frappe.db.delete("User Permission", {
                    "user": user,
                    "allow": doc.doctype,
                    "for_value": doc.name
                })

def work_order_validate(doc, method):
    if doc.has_value_changed("bom_no") and hasattr(doc, "meter_per_roll"):
        meter = doc.qty if doc.stock_uom == "米" else 0
        roll = 0
        for row in doc.required_items:
            if row.stock_uom == "卷":
                roll = row.required_qty
                break
        if meter and roll:
            doc.meter_per_roll = meter / roll

def work_order_on_submit(doc, method):
    if doc.operations and get_cached_value("work_order_is_tracking_number"):
        tracking_doc = frappe.new_doc("Tracking Number")
        tracking_doc.update({
            "tracking_number": doc.name,
            "work_order": doc.name,
            "item_code": doc.production_item,
            "item_name": doc.item_name,
            "qty": doc.qty
        })
        tracking_doc.insert(ignore_permissions=True)
        frappe.db.set_value("Job Card", {
            "work_order": doc.name,
            "docstatus": 0,
            "tracking_number": ("is", "not set")
        }, "tracking_number", doc.name
        )

def item_validate(doc, method):
    """
    将多规格物料的某个属性值回写到属性主数据设置的物料自定义字段
    """
    
    if doc.variant_of:
        custom_field = frappe.qb.DocType("Custom Field")
        item_attribute =  frappe.qb.DocType("Item Attribute")
        data = frappe.qb.from_(item_attribute
        ).join(custom_field
        ).on(custom_field.name == item_attribute.item_custom_field
        ).where(
            item_attribute.name.isin([r.attribute for r in doc.attributes])
        ).select(
            item_attribute.name,
            custom_field.fieldname
        ).run(as_list=1)
        attribute_field_map = frappe._dict(data)
        if attribute_field_map:
            for row in doc.attributes:
                field = attribute_field_map.get(row.attribute)
                if field:
                    doc.set(field, row.attribute_value)
    if doc.variant_based_on == "Item Attribute" and doc.variant_of and frappe.flags.in_import:
        sync_variant_item_name(doc)

def sync_variant_item_name(doc):
    from erpnext.controllers.item_variant  import make_variant_item_code
    
    variant = doc.as_dict()
    variant.item_code = None # 让make_variant_item_code生成物料号与物料名，物料不需要用到而已
    template_item_name = frappe.db.get_value("Item", doc.variant_of, "item_name")
    make_variant_item_code(doc.variant_of, template_item_name, variant)
    doc.item_name = variant.item_name

def job_card_before_validate(doc, method):
    if get_cached_value("enable_time_in_mins"):
        doc.time_in_mins_map = {r.name:r.time_in_mins for r in doc.time_logs}

def job_card_validate(doc, method):
    """根据计价方式计算实际人工成本、委外加工成本"""
    if (get_cached_value("enable_time_in_mins") and hasattr(doc, "time_in_mins_map") and 
        doc.time_in_mins_map and doc.time_logs
    ):
        doc.total_time_in_mins = sum(doc.time_in_mins_map.get(d.name, 0) for d in doc.time_logs)
        
    if doc.custom_rate_type and (not doc.custom_service_price or doc.has_value_changed("custom_service_price")):
        doc.update_operation_price()

def create_remaining_qty_job_card(doc, method):
    """
    部分报工（修改生产数量），自动创建剩余数量job card
    """

    before_save = doc.get_doc_before_save()    
    if before_save and before_save.for_quantity > doc.for_quantity:
        new_doc = frappe.copy_doc(doc)
        new_doc.time_logs = []
        new_doc.for_quantity = before_save.for_quantity - doc.for_quantity        
        #new_doc.tracking_number = None  #这个还要再想想
        new_doc.flags.ignore_mandatory = True
        new_doc.save(ignore_permissions=1)